package com.stone.gateway.config;
import com.stone.gateway.dto.RouteDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

import static java.util.Collections.synchronizedMap;

/**
 * 路由管理
 * @author fxj
 */
@Slf4j
@Service
public class RouteDefinition implements RouteDefinitionLocator {

    /**
     * 路由信息缓存
     */
    private final Map<String, org.springframework.cloud.gateway.route.RouteDefinition> routes = synchronizedMap(
            new LinkedHashMap<String, org.springframework.cloud.gateway.route.RouteDefinition>());

    public void add(org.springframework.cloud.gateway.route.RouteDefinition r) {
        routes.put(r.getId(), r);
    }

    public void update(org.springframework.cloud.gateway.route.RouteDefinition r) {
        if (routes.containsKey(r.getId())) {
            routes.put(r.getId(), r);
        }
    }

    public void delete(String id) {
        if (routes.containsKey(id)) {
            routes.remove(id);
        }
    }

    public void clear() {
        routes.clear();
    }

    @Override
    public Flux<org.springframework.cloud.gateway.route.RouteDefinition> getRouteDefinitions() {
        reload();
        return Flux.fromIterable(routes.values());
    }

    public void reload() {
        //TODO1 加载配置数据
        List<RouteDTO> routes = new LinkedList<>();
        this.clear();
        for (RouteDTO routeDTO : routes) {
            try {
                this.addRoute(routeDTO);
            } catch (URISyntaxException e) {
                log.error("加载路由异常：" + routeDTO, e);
            }
        }
    }

    private void addRoute(RouteDTO routeDTO) throws URISyntaxException {
        org.springframework.cloud.gateway.route.RouteDefinition r = new org.springframework.cloud.gateway.route.RouteDefinition();
        r.setId(routeDTO.getId());
        r.setUri(new URI(routeDTO.getUri()));
        List<PredicateDefinition> predicates = new ArrayList<>();
        List<String> predicateList = routeDTO.getPredicates();
        for (String text:predicateList){
            PredicateDefinition predicateDefinition = new PredicateDefinition(text);
            predicates.add(predicateDefinition);
        }
        r.setPredicates(predicates);
        List<FilterDefinition> filters = new ArrayList<FilterDefinition>();
        List<String> filtersStr = routeDTO.getFilters();
        filtersStr.forEach(s -> {
            FilterDefinition filter = new FilterDefinition(s);
            filters.add(filter);
        });
        r.setFilters(filters);
        r.setMetadata(routeDTO.getMetadata());
        this.add(r);
    }

}